﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Summary description for Structures
/// </summary>
public interface IContentMap
{
    int Count();
    IComparable GetByIndex(int index);
}

internal enum DeltaStatus
{
    Matched = 1,
    NoMatch = -1,
    Unknown = -2

}

internal class DeltaStateList
{
    private DeltaState[] _array;

    public DeltaStateList(int destCount)
    {
        _array = new DeltaState[destCount];
    }

    public DeltaState GetByIndex(int index)
    {
        DeltaState retval = _array[index];
        if (retval == null)
        {
            retval = new DeltaState();
            _array[index] = retval;
        }
        return retval;
    }
}

internal class DeltaState
{
    private const int INVALID_IDX = -1;
    private int _startIndex;
    private int _length;

    public int StartIndex { get { return _startIndex; } }
    public int EndIndex { get { return ((_startIndex + _length) - 1); } }
    public int Length
    {
        get
        {
            int len;
            if (_length > 0)
            {
                len = _length;
            }
            else
            {
                if (_length == 0)
                {
                    len = 1;
                }
                else
                {
                    len = 0;
                }
            }
            return len;
        }
    }

    public DeltaStatus Status
    {
        get
        {
            DeltaStatus status = DeltaStatus.Unknown;

            if (_length > 0)
            {
                status = DeltaStatus.Matched;
            }
            else if (_length == -1)
            {
                status = DeltaStatus.NoMatch;
            }
            return status;
        }
    }

    public DeltaState()
    {
        SetToUnkown();
    }

    protected void SetToUnkown()
    {
        _startIndex = INVALID_IDX;
        _length = (int)DeltaStatus.Unknown;
    }

    public void SetMatch(int start, int length)
    {
        _startIndex = start;
        _length = length;
    }

    public void SetNoMatch()
    {
        _startIndex = INVALID_IDX;
        _length = (int)DeltaStatus.NoMatch;
    }


    public bool HasValidLength(int newStart, int newEnd, int maxPossibleDestLength)
    {
        if (_length > 0) //have unlocked match
        {
            if ((maxPossibleDestLength < _length) ||
                ((_startIndex < newStart) || (EndIndex > newEnd)))
            {
                SetToUnkown();
            }
        }
        return (_length != (int)DeltaStatus.Unknown);
    }
}

public enum DeltaResultStatus
{
    Match,
    ReplaceMap1,
    DeleteMap1,
    AddMap2
}

public class DeltaResult : IComparable
{
    private const int INVALID_IDX = -1;
    private int _map2IDX;
    private int _map1IDX;
    private int _length;
    private DeltaResultStatus _status;

    public int Map2IDX { get { return _map2IDX; } }
    public int Map1IDX { get { return _map1IDX; } }
    public int Length { get { return _length; } }
    public DeltaResultStatus Status { get { return _status; } }

    protected DeltaResult(
        DeltaResultStatus status,
        int map2IDX,
        int map1IDX,
        int length)
    {
        _status = status;
        _map2IDX = map2IDX;
        _map1IDX = map1IDX;
        _length = length;
    }

    public static DeltaResult AddNewMatchResult(int map2IDX, int map1IDX, int length)
    {
        return new DeltaResult(DeltaResultStatus.Match, map2IDX, map1IDX, length);
    }

    public static DeltaResult AddNewReplaceMap1Result(int map2IDX, int map1IDX, int length)
    {
        return new DeltaResult(DeltaResultStatus.ReplaceMap1, map2IDX, map1IDX, length);
    }

    public static DeltaResult AddNewDeleteMap1Result(int map1IDX, int length)
    {
        return new DeltaResult(DeltaResultStatus.DeleteMap1, INVALID_IDX, map1IDX, length);
    }

    public static DeltaResult AddNewAddMap2Result(int map2IDX, int length)
    {
        return new DeltaResult(DeltaResultStatus.AddMap2, map2IDX, INVALID_IDX, length);
    }

    public void AddLength(int i)
    {
        _length += i;
    }

   
    #region IComparable Members

    public int CompareTo(object obj)
    {
        return _map2IDX.CompareTo(((DeltaResult)obj)._map2IDX);
    }

    #endregion

}
